#include "PWM.H"

/**
    ******************************************************************************
    * @brief  配置TIM2通道2为PWM输出模式
    * @param  无
    * @retval 无
    * @note   输出引脚: PA1 (TIM2_CH2)
    *         PWM频率: 20kHz
    *         占空比范围: 0.0% - 100.0%
    *         系统时钟: 72MHz
    ******************************************************************************
*/
void PWM_Config(void)
{
    // 使能外设时钟
    // RCC_APB2Periph_GPIOA: 使能GPIOA时钟 (控制PA1引脚)
    // RCC_APB2Periph_AFIO: 使能复用功能时钟 (连接TIM2到PA1)
    RCC_APB2PeriphClockCmd(PWM_CLK | RCC_APB2Periph_AFIO, ENABLE);
    
    // 配置PA1为复用推挽输出模式
    // 复用功能: 将引脚控制权交给TIM2_CH2
    // 推挽输出: 可主动输出高/低电平，驱动能力强
    GPIO_InitTypeDef GPIO_InitStructure = {
        .GPIO_Mode  = GPIO_Mode_AF_PP,    // 复用推挽输出模式
        .GPIO_Pin   = PWM_PIN,        // 选择PA1引脚 (TIM2_CH2)
        .GPIO_Speed = GPIO_Speed_50MHz,  // 设置引脚最大翻转速度为50MHz
    };
    GPIO_Init(PWM_PORT, &GPIO_InitStructure);
    
    // 使能TIM2时钟 (挂载在APB1总线上)
    // APB1总线时钟为36MHz，TIM2时钟 = APB1时钟 × 2 = 72MHz
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 配置TIM2使用内部时钟源 (CK_INT)
    // 内部时钟来源: SYSCLK(72MHz) → AHB分频器(1) → APB1分频器(2) → TIM2时钟(72MHz)
    TIM_InternalClockConfig(TIM2);

    // 配置TIM2时基单元 - 决定PWM频率
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {
        // 时钟分频因子，用于定时器采样时钟
        // 影响数字滤波器(ETR, TIx)的采样频率，此处不使用
        .TIM_ClockDivision = TIM_CKD_DIV1,    
        
        // 向上计数模式: 计数器从0递增到ARR值，然后重置为0
        // 向下计数模式: 计数器从ARR值递减到0，然后重置为ARR
        .TIM_CounterMode = TIM_CounterMode_Up,
        
        // 自动重载寄存器值(ARR)
        // 决定PWM周期: 计数器从0计数到ARR后重置
        // ARR = 99，计数器范围0-99，共100个计数周期
        .TIM_Period = 100 - 1,               
        
        // 预分频器值(PSC)
        // 系统时钟(72MHz) → 预分频器 → 定时器时钟
        // 定时器时钟 = 系统时钟/(PSC+1) = 72MHz/36 = 2MHz
        .TIM_Prescaler = 36 - 1,             
        
        // 重复计数器值(高级定时器有效)
        // 每完成N次更新事件才触发一次中断/更新
        // 此处设为0，表示每个更新事件触发一次
        .TIM_RepetitionCounter = 0,           
    };
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);

    // 初始化PWM输出配置结构
    TIM_OCInitTypeDef TIM_OCInitStructure;
    // 将结构体初始化为默认值，避免未定义参数影响配置
    TIM_OCStructInit(&TIM_OCInitStructure);  
    
    // 配置TIM2通道2为PWM模式1
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;      
    // PWM模式1工作原理:
    // 当计数器值(CNT) < 比较值(CCR2)时，输出高电平
    // 当计数器值(CNT) >= 比较值(CCR2)时，输出低电平
    
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
    // 输出极性配置:
    // TIM_OCPolarity_High: 有效电平为高电平
    // TIM_OCPolarity_Low: 有效电平为低电平
    
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
    // 使能通道输出，将PWM信号传输到引脚
    
    TIM_OCInitStructure.TIM_Pulse = 0;                     
    // 初始比较值(CCR2)为0，占空比0%
    // CCR2值决定高电平持续时间
    
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);               
    // 应用配置到TIM2通道2(对应PA1引脚)
    // 此函数会设置TIM2_CCMR1寄存器的OC2M位为110(PWM模式1)
    
    // 使能自动重载寄存器(ARR)的预装载功能
    // 预装载: 新的ARR值不会立即生效，而是在更新事件(UEV)后生效
    // 作用: 保证PWM周期的完整性，避免中途改变ARR导致波形异常
    TIM_ARRPreloadConfig(TIM2, ENABLE);
    
    // 使能通道2的输出比较预装载功能
    // 新的CCR2值会在更新事件后生效，避免占空比突变
    TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

    // 启动TIM2计数器
    // 使能TIM2_CR1寄存器的CEN位，开始计数
    // 定时器开始工作，PWM信号开始输出
    TIM_Cmd(TIM2, ENABLE);
}

/**
    ******************************************************************************
    * @brief  设置TIM2通道2的PWM占空比
    * @param  Compare: 比较值(CCR2)，范围0~99
    * @retval 无
    * @note   占空比计算公式: 占空比 = (Compare/99)×100%
    *         例如: Compare=50 → 占空比≈50.5%
    ******************************************************************************
*/
void PWM_SetCompare2(u16 Compare)
{
    // 设置TIM2通道2的捕获比较寄存器值(CCR2)
    // CCR2值决定了PWM信号的占空比
    // 在PWM模式1下:
    //   当CNT < CCR2时，输出高电平
    //   当CNT >= CCR2时，输出低电平
    TIM_SetCompare2(TIM2, Compare);
    
    // 占空比计算示例:
    // 当Compare=0时，CNT始终≥CCR2，输出始终为低 → 占空比0%
    // 当Compare=49时，CNT在0-48时输出高，49-99时输出低 → 占空比=49/99≈49.5%
    // 当Compare=99时，CNT在0-98时输出高，99时输出低 → 占空比=99/99=100%
}
